package visual;

import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.table.AbstractTableModel;

import creatures.ICreature;

@SuppressWarnings("serial")
public class StatisticTableModel extends AbstractTableModel {
	
	/**
	 * List of the creatures
	 */
	private ArrayList<? extends ICreature> creatures;
	
	/**
	 * Names of the column
	 */
	private String[] columnNames = { "Creature", "Number of creature", "Number of birth" };
	
	/**
	 * Datas to display
	 */
	private Object[][] data;
	
	/**
	 * Classes of the creatures
	 */
	private ArrayList<String> creaturesClass;
	
	/**
	 * Number of creatures at each clock's ticks
	 */
	private ArrayList<ArrayList<Integer>> creaturesDatas = new ArrayList<ArrayList<Integer>>();
	
	/**
	 * Number of birth of each creatures
	 */
	private HashMap<String,Integer> birthCount = new HashMap<String, Integer>();
	
	public StatisticTableModel(ArrayList<? extends ICreature> creatures, ArrayList<String> pluginsNames) {
		this.creatures = creatures;
		this.creaturesClass = pluginsNames;
		this.data = new Object[creaturesClass.size()][3];
		for(int j = 0; j < creaturesClass.size(); j++) {
			Object[] d = { creaturesClass.get(j).substring(creaturesClass.get(j).lastIndexOf(".")+1), 0, 0 };
			this.data[j] = d;
			ArrayList<Integer> creatureData = new ArrayList<Integer>();
			this.creaturesDatas.add(creatureData);
			this.birthCount.put(creaturesClass.get(j), 0);
		}
		this.countCreatures();
	}
	
	@Override
	public void setValueAt(Object value, int row, int col) {
		if (this.isEditable(row, col)) {
			this.data[row][col] = value;
			fireTableCellUpdated(row, col);
		}
	}
	
	/**
	 * 
	 * @param row
	 * @param col
	 * @return
	 */
	private boolean isEditable(int row, int col) {
		if (col < 1) {
			return false;
		}
		return true;
	}

	@Override
	public int getColumnCount() {
		return this.columnNames.length;
	}

	@Override
	public int getRowCount() {
		return this.data.length;
	}

	@Override
	public Object getValueAt(int row, int col) {
		return this.data[row][col];
	}
	
	@Override
	public String getColumnName(int col) {
		return this.columnNames[col];
	}
	
	/**
	 * 
	 * @return creaturesDatas
	 */
	public ArrayList<ArrayList<Integer>> getCreaturesDatas() {
		return this.creaturesDatas;
	}
	
	/**
	 * 
	 * @return pluginNames, the array of the creatures's names
	 */
	public ArrayList<String> getPluginNames() {
		ArrayList<String> pluginNames = new ArrayList<String>();
		for (Object[] d : this.data) {
			pluginNames.add((String)d[0]);
		}
		return pluginNames;
	}
	
	/**
	 * Counts the each type of creatures
	 */
	public void countCreatures() {
		for (int i = 0; i < this.creaturesDatas.size(); i++) {
			int count = 0;
			for(ICreature c : this.creatures) {
				if (c.getClass().toString().substring(6).equals(this.creaturesClass.get(i))) {
					count++;
				}
			}
			this.creaturesDatas.get(i).add(count);
			this.setValueAt(count, i, 1);
		}
	}
	
	/**
	 * Refreshes the list of the creatures
	 * {@link #creatures}
	 * 
	 * @param creatures
	 */
	public void refreshCreatures(ArrayList<? extends ICreature> creatures) {
		this.creatures = creatures;
		this.countCreatures();
	}
	
	/**
	 * Increases the birth count of the type of the following creature
	 * {@link #birthCount}
	 * 
	 * @param creature
	 */
	public void increaseBirth(ICreature creature) {
		for (int i = 0; i < this.creaturesClass.size(); i++) {
			if (creature.getClass().toString().substring(6).equals(this.creaturesClass.get(i))){
				int value = this.birthCount.get(this.creaturesClass.get(i));
				value++;
				this.setValueAt(value, i, 2);
				this.birthCount.remove(this.creaturesClass.get(i));
				this.birthCount.put(this.creaturesClass.get(i), value);
			}
		}
	}
	
	/**
	 * 
	 * @return data
	 */
	public Object[][] getDatas() {
		return this.data;
	}

}
